/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.unesp.ia.gridsolver.beans;

import com.unesp.ia.gridsolver.csp.GridScheduler;
import com.unesp.ia.gridsolver.csp.TSPData;
import com.unesp.ia.gridsolver.csp.TSPSchedule;
import com.unesp.ia.gridsolver.entity.Aluno;
import com.unesp.ia.gridsolver.entity.Curso;
import com.unesp.ia.gridsolver.session.AlunoFacade;
import com.unesp.ia.gridsolver.session.CursoFacade;
import com.unesp.ia.gridsolver.session.MateriaFacade;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

/**
 *
 * @author Pardal
 */
@ManagedBean(name = "cspTestBean")
@RequestScoped
public class SchedulerBean {

    @EJB
    private CursoFacade cursoFacade;
    @EJB
    private AlunoFacade alunoFacade;
    @EJB
    private MateriaFacade materiaFacade;
    Curso c;
    Aluno a;
    private int minAno;
    private int idAluno;
    private int idCurso;
    private boolean feasible;    
    List<TSPSchedule> rawSchedule;
    List<List<List<List<String>>>> schedule;

    /**
     * Creates a new instance of TestBean
     */
    public SchedulerBean() {
    }

    public void fillTSPData() {
        c = cursoFacade.find(idCurso);
        a = alunoFacade.find(idAluno);
        TSPData data = new TSPData(a, c, materiaFacade);
        data.prettyOut();
        GridScheduler scheduler = new GridScheduler(data);
        scheduler.execute();
        if (scheduler.optimalSolve()) {
            scheduler.prettyOut();
            rawSchedule = scheduler.buildSchedule();
            for (TSPSchedule materia : rawSchedule) {
                materia.setMateria(materiaFacade.find(materia.getIdMateria()));
                int ano = materia.getHorarios().get(0) / 36;
                int semestre = (materia.getHorarios().get(0) / 18) - (ano * 2);
                System.out.println("\n Matéria: " + materia.getMateria().getNome() + "(" + materia.getIdMateria() + ")");
                System.out.println("\t >ANO: " + (ano + 1) + " " + materia.getAno());
                System.out.println("\t >SEMESTRE: " + (semestre + 1) + " " + materia.getSemestre());
                for (Integer i : materia.getHorarios()) {
                    int ordinal = i - (ano * 36);
                    TSPData.Horario h = TSPData.Horario.values()[ordinal];
                    System.out.println("\t >Horário: " + h.getNome());
                }
            }
            feasible = true;
            parseToChart();
        } else {
            feasible = false;
        }        
    }

    public void parseToChart() {
        int maxAno = 0;
        minAno = a.getSemestre() / 3;
        for (TSPSchedule mat : rawSchedule) {
            if (mat.getAno() > maxAno) {
                maxAno = mat.getAno();
            }
        }
        // Prime timetable
        //                  Ano  Sem  Peri Dias Materia
        schedule = new ArrayList<List<List<List<String>>>>(); // Anos
        for (int i = 0; i < (maxAno - minAno + 1); i++) {
            schedule.add(new ArrayList<List<List<String>>>()); // Semestres
            for (int j = 0; j < 2; j++) {
                schedule.get(i).add(new ArrayList<List<String>>()); // Períodos
                for (int k = 0; k < 3; k++) {
                    schedule.get(i).get(j).add(new ArrayList<String>()); // Dias
                    for (int l = 0; l < 6; l++) {
                        schedule.get(i).get(j).get(k).add(new String("")); // Matéria
                    }
                }
            }
        }
        // Place subjects
        for (TSPSchedule m : rawSchedule) {
            for (Integer i : m.getHorarios()) {
                int ordinal = i - (m.getAno() * 36);
                TSPData.Horario h = TSPData.Horario.values()[ordinal];
                int ano = m.getAno() - minAno;
                int semestre = h.getSemestre();
                int periodo = h.getPeriodo();
                int diasem = h.getDiaSem();
                String nome = m.getMateria().getNome();
                schedule.get(ano).get(semestre).get(periodo).set(diasem, nome);
            }
        }
    }

    public List<List<List<List<String>>>> getSchedule() {
        return schedule;
    }

    public void setSchedule(List<List<List<List<String>>>> schedule) {
        this.schedule = schedule;
    }

    public int getMinAno() {
        return minAno + 1;
    }

    public void setMinAno(int minAno) {
        this.minAno = minAno;
    }

    public boolean isFeasible() {
        return feasible;
    }  
    
    public List<Aluno> listAlunos() {
        return alunoFacade.findAll();        
    }
    
    public List<Curso> listCursos() {
        return cursoFacade.findAll();
    }

    public int getIdAluno() {
        return idAluno;
    }

    public void setIdAluno(int idAluno) {
        this.idAluno = idAluno;
    }

    public int getIdCurso() {
        return idCurso;
    }

    public void setIdCurso(int idCurso) {
        this.idCurso = idCurso;
    }        
    
}
